import { createClient } from '@supabase/supabase-js'
import { NextResponse } from 'next/server'
import type { UpdateFileSystemItemRequest } from '@/lib/types/database'
// Create server-side Supabase client with user session
function createServerSupabaseClient(request: Request) {
// Get the authorization header from the request
const authHeader = request.headers.get('authorization')
return createClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
{
auth: {
autoRefreshToken: false,
persistSession: false
},
global: {
headers: authHeader ? {
Authorization: authHeader
} : {}
}
}
)
}
// GET /api/books/[id]/files/[fileId] - Get a specific file
export async function GET(
request: Request,
{ params }: { params: { id: string; fileId: string } }
) {
try {
const supabase = createServerSupabaseClient(request)
const bookId = params.id
const fileId = params.fileId
// Get the file system item (RLS will handle access control)
const { data: item, error } = await supabase
.from('file_system_items')
.select('*')
.eq('id', fileId)
.eq('book_id', bookId)
.single()
if (error || !item) {
return NextResponse.json(
{ error: 'File not found' },
{ status: 404 }
)
}
return NextResponse.json({ item })
} catch (error) {
console.error('Error in GET /api/books/[id]/files/[fileId]:', error)
return NextResponse.json(
{ error: 'Internal server error' },
{ status: 500 }
)
}
}
// PUT /api/books/[id]/files/[fileId] - Update a file or folder
export async function PUT(
request: Request,
{ params }: { params: { id: string; fileId: string } }
) {
try {
const supabase = createServerSupabaseClient(request)
const bookId = params.id
const fileId = params.fileId
const body: UpdateFileSystemItemRequest = await request.json()
// Check if file exists (RLS will handle access control)
const { data: existingItem, error: existingError } = await supabase
.from('file_system_items')
.select('*')
.eq('id', fileId)
.eq('book_id', bookId)
.single()
if (existingError || !existingItem) {
return NextResponse.json(
{ error: 'File not found' },
{ status: 404 }
)
}
// If moving to a new parent, validate parent exists and is a folder
if (body.parent_id && body.parent_id !== existingItem.parent_id) {
const { data: parent, error: parentError } = await supabase
.from('file_system_items')
.select('id, type')
.eq('id', body.parent_id)
.eq('book_id', bookId)
.single()
if (parentError || !parent) {
return NextResponse.json(
{ error: 'Parent folder not found' },
{ status: 400 }
)
}
if (parent.type !== 'folder') {
return NextResponse.json(
{ error: 'Parent must be a folder' },
{ status: 400 }
)
}
}
// Prepare update data
const updateData: any = {}
if (body.name !== undefined) updateData.name = body.name
if (body.content !== undefined) updateData.content = body.content
if (body.expanded !== undefined) updateData.expanded = body.expanded
if (body.sort_order !== undefined) updateData.sort_order = body.sort_order
if (body.parent_id !== undefined) updateData.parent_id = body.parent_id
// Update the item
const { data: updatedItem, error } = await supabase
.from('file_system_items')
.update(updateData)
.eq('id', fileId)
.eq('book_id', bookId)
.select()
.single()
if (error) {
console.error('Error updating file system item:', error)
return NextResponse.json(
{ error: 'Failed to update item' },
{ status: 500 }
)
}
return NextResponse.json({
item: updatedItem,
message: 'Item updated successfully'
})
} catch (error) {
console.error('Error in PUT /api/books/[id]/files/[fileId]:', error)
return NextResponse.json(
{ error: 'Internal server error' },
{ status: 500 }
)
}
}
// DELETE /api/books/[id]/files/[fileId] - Delete a file or folder
export async function DELETE(
request: Request,
{ params }: { params: { id: string; fileId: string } }
) {
try {
const supabase = createServerSupabaseClient(request)
const bookId = params.id
const fileId = params.fileId
// Check if item exists (RLS will handle access control)
const { data: existingItem, error: existingError } = await supabase
.from('file_system_items')
.select('id, type, name')
.eq('id', fileId)
.eq('book_id', bookId)
.single()
if (existingError || !existingItem) {
return NextResponse.json(
{ error: 'Item not found' },
{ status: 404 }
)
}
// Delete the item - CASCADE DELETE will handle children automatically
const { error: deleteError } = await supabase
.from('file_system_items')
.delete()
.eq('id', fileId)
.eq('book_id', bookId)
if (deleteError) {
console.error('Error deleting file system item:', deleteError)
return NextResponse.json(
{ error: 'Failed to delete item' },
{ status: 500 }
)
}
return NextResponse.json({
message: `${existingItem.type === 'file' ? 'File' : 'Folder'} deleted successfully`
})
} catch (error) {
console.error('Error in DELETE /api/books/[id]/files/[fileId]:', error)
return NextResponse.json(
{ error: error instanceof Error ? error.message : 'Internal server error' },
{ status: 500 }
)
}
}